package com.AdvancedDemos.接口;

public class Interface {
    public static void main(String[] args) {

        /**
         * 接口体现的是:
         *  1.规则标准的制定
         *  2.功能扩展
         *
         * 继承体现的是:
         *  公共属性和行为的抽取
         */

        System.out.println(A.MY_NAME);//接口中的 常量 可以用 接口名.常量名 调用
        System.out.println("-------------");

        /*接口不能实例化,需要用关键字 implements 来实现,实现接口的类称为 实现类 ,也即对应于继承父类的 子类*/

        /**
         * 接口弥补了类无法多继承的问题
         *
         *一个类不可以多继承,只能继承链,因为如果一个类继承了多个父类,那么构造函数中super就不知道指的是哪个父类了;不同的是一个类可以实现多个接口,因为接口不存在构造的问题;同时,一个接口又可以继承多个其他接口,则实现类只需要实现这一个接口就可以同时实现所有接口
         *************************************
         * 修饰符 class 实现类名 implements 接口1,接口2,接口3,... {
         *
         * }
         *************************************
         * 实现类实现多个接口,必须完全重写全部接口的抽象函数,否则该实现类也需要定义为抽象类
         *
         */

        D d = new D();
        d.testb1();
        d.testb2();
        d.testc1();
        d.testc2();
        System.out.println("-------------");

        /**
         * 就像通过 父类变量 指向 子类实例 实现多态一样
         * 可以用 接口类型的引用  变量 指向实现类的实例 来实现多态
         */
        B b = new D();
        C c = new D();
        E e = new D();

        d.BC接口同名函数();
        d.BC接口同名默认函数();


        System.out.println("-------------");
        Zi zi = new Zi();
        zi.run();//父类的run方法执行了
        System.out.println("-------------");


    }
}

/**
 * public interface 接口名 {
 * //成员变量(默认是常量,即 public final static 修饰的,需要赋初值)
 * //成员方法(默认是抽象方法)
 * }
 */

abstract interface A {//接口默认就是抽象的,修饰符 'abstract' 对于接口是冗余的
    public final static String MY_NAME = "一土一大土立方";//即使不加public static final 也是常量

    public abstract void memberMethod();//即使不加 public abstract 也默认是抽象方法,不能有方法体

    /*接口不能有构造函数,无法实例化*/
//    public A(){ }
    /*接口不能有"静态/构造/局部代码块"*/
//    static{ }
//    { }
}

interface B {
    void testb1();

    void testb2();

    public void BC接口同名函数();

    public default void BC接口同名默认函数() {
        System.out.println("我是B接口中的默认函数");
    }
}

interface C {
    void testc1();

    void testc2();

    public void BC接口同名函数();

    public default void BC接口同名默认函数() {
        System.out.println("我是C接口中的默认函数");
    }
}

class E {
}

interface B_C extends B, C {//一个类不可以多继承,只能继承链,因为如果一个类继承了多个父类,那么构造函数中super就不知道指的是哪个父类了;不同的是一个类可以实现多个接口,因为接口不存在构造的问题;同时,一个接口又可以继承多个其他接口,则实现类只需要实现这一个接口就可以同时实现所有接口


    @Override
    default void BC接口同名默认函数() {
        //重写BC接口中冲突的默认函数,否则报错
    }
}


class D extends E implements B, C {//可以继承父类,又同时实现接口

    @Override
    public void testb1() {
        System.out.println("testb1");
    }

    @Override
    public void testb2() {
        System.out.println("testb2");
    }

    @Override
    public void testc1() {
        System.out.println("testc1");
    }

    @Override
    public void testc2() {
        System.out.println("testc2");
    }

    @Override
    public void BC接口同名函数() {
        System.out.println("BC接口中的同名函数在实现类D中重写");
    }//当一个 类/接口 实现多个接口时,如果这些接口中含有相同签名(返回值,函数名,参数列表)的抽象方法,那么在实现类中只会重写实现一次,把两个接口中的抽象方法都覆盖

    //一个 类/接口 继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承 , 例如: 如果两个接口中的抽象函数 函数名,参数列表 都一样,但是 返回值不同,此时会发生冲突,无论实现类中选择哪一个返回类型的来重写实现,都会报错,因为与另一个接口中的同名抽象函数冲突了,如果不管重名强行同时写出两个方法各自的实现,他们之间互相又会因为同名而冲突,所以无论如何都会报错!

    @Override
    public void BC接口同名默认函数() {
        System.out.println("我是D类中重写BC接口同名默认函数的函数");
    }

}

//一个类继承了父类,又同时实现了接口,父类和接口中有同名的默认方法, 实现/子 类会优先用父类的,即继承关系优先级高于实现关系
class Fu {
    public void run() {
        System.out.println("父类的run方法执行了");
    }
}

interface I {
    default void run() {
        System.out.println("接口中的方法执行了");
    }
}

class Zi extends Fu implements I {

}
